#ifndef __MYCOMPLEX__
#define __MYCOMPLEX__
#include <cmath>

class complex;                                           // 声明全局函数
complex& 
    __doapl(complex* ths, const complex& r);            // do assignment plus
complex& 
    __doami(complex* ths, const complex& r);            // do assignment minus
complex& 
    __doaml(complex* ths, const complex& r);            // do assignment multiplication

class complex {
public:
    complex(double r = 0,double i = 0): re(r), im(i) {}  // 构造函数，采用初始化列表进行成员变量初始化
    complex& operator += (const complex& r);             // 操作符重载函数声明
    complex& operator -= (const complex& r);
    complex& operator *= (const complex& r);
    // complex& operator /= (const complex& r);
    double real() const { return re; }                   // 使用const修饰函数，使得函数不会修改成员变量
    double imag() const { return im; }
private:
    double re,im;

    friend complex& __doapl(complex* ths, const complex& r);  // 声明友元函数
    friend complex& __doami(complex* ths, const complex& r);
    friend complex& __doaml(complex* ths, const complex& r);
};

inline complex&                                              // 友元函数定义
__doapl(complex* ths, const complex& r) {
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

inline complex&                                             // += 操作符重载
complex::operator += (const complex& r) {
    return __doapl(this,r);
}

inline complex&                                              // 友元函数定义
__doami(complex* ths, const complex& r) {
    ths->re -= r.re;
    ths->im -= r.im;
    return *ths;
}

inline complex&                                              // -= 操作符重载
complex::operator -= (const complex& r) {
    return __doami(this,r);
}

inline complex&                                              // 友元函数定义
__doaml(complex* ths, const complex& r) {
    double f = ths->re * r.re - ths->im * r.im;
    ths->im = ths->re * r.im + ths->im * r.re;
    ths->re = f;
    return *ths;
}

inline complex&                                              // *= 操作符重载
complex::operator *= (const complex& r) {
    return __doaml(this,r);
}

inline double
real (const complex& x) {
    return x.real();
}

inline double
imag (const complex& x) {
    return x.imag();
}

inline complex                                              // 两个复数相加
operator + (const complex& x,const complex& y) {
    return complex(real(x) + real(y) , imag(x) + imag(y));  // 返回局部变量，所有不能返回reference，只能返回值
}

inline complex                                              // 复数与常数相加
operator + (const complex& x,const double y) {
    return complex(real(x) + y , imag(x));
}

inline complex                                              // 常数与复数相加
operator + (const double x,const complex& y) {
    return complex(x + real(y) , imag(y));
}

inline complex                                              // 两个复数相减
operator - (const complex& x,const complex& y) {
    return complex(real(x) - real(y) , imag(x) - imag(y));
}

inline complex                                              // 复数与常数相减
operator - (const complex& x,const double y) {
    return complex(real(x) - y , imag(x));
}

inline complex                                              // 常数与复数相减
operator - (const double x,const complex& y) {
    return complex(x - real(y) , imag(y));
}

inline complex                                              // 两个复数相乘
operator * (const complex& x,const complex& y) {
    return complex(real(x) * real(y) - imag(x) * imag(y),
                   real(x) * imag(y) + imag(x) * real(y));
}       

inline complex                                              // 复数与常数相乘
operator * (const complex& x,const double y) {
    return complex(real(x) * y , imag(x) * y);
}

inline complex                                              // 常数与复数相乘
operator * (const double x,const complex& y) {
    return complex(x * real(y) , x * imag(y));
}

complex 
operator / (const complex& x, const double y) {             // 复数与常数相除
    return complex(real(x) / y , imag(x) / y);
}

inline complex 
operator + (const complex& x) {
    return x;
}

inline complex 
operator - (const complex& x) {
    return complex(-real(x),-imag(x));
}

inline bool
operator == (const complex& x,const complex& y) {
    return real(x) == real(y) && imag(x) == imag(y);
}

inline bool
operator == (const complex& x,const double y) {
    return real(x) == y && imag(x) == 0;
}

inline bool
operator == (const double x,const complex& y) {
    return x == real(y) && imag(y) == 0;
}

inline bool
operator != (const complex& x,const complex& y) {
    return real(x) != real(y) || imag(x) != imag(y);
}

inline bool
operator != (const complex& x,const double y) {
    return real(x) != y || imag(x) != 0;
}

inline bool
operator != (const double x,const complex& y) {
    return x != real(y) || imag(y) != 0;
}

inline complex 
polar (double r,double t) {
    return complex(r * cos(t), r * sin(t));
}

inline complex
conj (const complex& x) {
    return complex(real(x), -imag(x));
}

inline double
norm (const complex& x) {
    return real(x) * real(x) + imag(x) * imag(x);
}

#endif  // __MYCOMPLEX__